package com.property.demo.service.impl;

import com.property.demo.model.Home;
import com.property.demo.model.Owner;
import com.property.demo.model.Repair;
import com.property.demo.repository.HomeRepository;
import com.property.demo.repository.OwnerRepository;
import com.property.demo.repository.RepairRepository;
import com.property.demo.service.RepairService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@Service
public class RepairServiceImpl implements RepairService {

    @Autowired
    private RepairRepository repairRepository;
    
    @Autowired
    private OwnerRepository ownerRepository;
    
    @Autowired
    private HomeRepository homeRepository;

    @Override
    public List<Repair> findAll() {
        return repairRepository.findAll();
    }

    @Override
    public Page<Repair> findAll(Pageable pageable) {
        return repairRepository.findAll(pageable);
    }

    @Override
    public Page<Repair> findByFilters(Long ownerId, Long homeId, String description, String status, String type, Pageable pageable) {
        Specification<Repair> spec = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            if (ownerId != null) {
                predicates.add(criteriaBuilder.equal(root.get("owner").get("id"), ownerId));
            }
            
            if (homeId != null) {
                predicates.add(criteriaBuilder.equal(root.get("home").get("id"), homeId));
            }
            
            if (description != null && !description.isEmpty()) {
                predicates.add(criteriaBuilder.like(criteriaBuilder.lower(root.get("description")), "%" + description.toLowerCase() + "%"));
            }
            
            if (status != null && !status.isEmpty()) {
                predicates.add(criteriaBuilder.equal(root.get("status"), status));
            }
            
            if (type != null && !type.isEmpty()) {
                predicates.add(criteriaBuilder.equal(root.get("type"), type));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
        
        return repairRepository.findAll(spec, pageable);
    }

    @Override
    public Optional<Repair> findById(Long id) {
        return repairRepository.findById(id);
    }

    @Override
    public Repair save(Repair repair) {
        if (repair.getOwner() != null && repair.getOwner().getId() != null) {
            Optional<Owner> owner = ownerRepository.findById(repair.getOwner().getId());
            owner.ifPresent(repair::setOwner);
        }
        
        if (repair.getHome() != null && repair.getHome().getId() != null) {
            Optional<Home> home = homeRepository.findById(repair.getHome().getId());
            home.ifPresent(repair::setHome);
        }
        
        return repairRepository.save(repair);
    }

    @Override
    public Repair update(Long id, Repair repairDetails) {
        Optional<Repair> optionalRepair = repairRepository.findById(id);
        if (optionalRepair.isPresent()) {
            Repair existingRepair = optionalRepair.get();
            
            if (repairDetails.getOwner() != null && repairDetails.getOwner().getId() != null) {
                Optional<Owner> owner = ownerRepository.findById(repairDetails.getOwner().getId());
                owner.ifPresent(existingRepair::setOwner);
            }
            
            if (repairDetails.getHome() != null && repairDetails.getHome().getId() != null) {
                Optional<Home> home = homeRepository.findById(repairDetails.getHome().getId());
                home.ifPresent(existingRepair::setHome);
            }
            
            existingRepair.setDescription(repairDetails.getDescription());
            existingRepair.setType(repairDetails.getType());
            existingRepair.setStatus(repairDetails.getStatus());
            existingRepair.setHandleTime(repairDetails.getHandleTime());
            existingRepair.setFinishTime(repairDetails.getFinishTime());
            existingRepair.setHandlerName(repairDetails.getHandlerName());
            existingRepair.setResult(repairDetails.getResult());
            
            return repairRepository.save(existingRepair);
        }
        return null;
    }

    @Override
    @Transactional
    public void delete(Long id) {
        repairRepository.deleteById(id);
    }

    @Override
    @Transactional
    public void deleteAll(List<Long> ids) {
        repairRepository.deleteAllById(ids);
    }

    @Override
    public List<Repair> findByOwnerId(Long ownerId) {
        return repairRepository.findByOwnerId(ownerId);
    }

    @Override
    public List<Repair> findByHomeId(Long homeId) {
        return repairRepository.findByHomeId(homeId);
    }

    @Override
    public List<Repair> findByStatus(String status) {
        return repairRepository.findByStatus(status);
    }

    @Override
    public List<Repair> findByType(String type) {
        return repairRepository.findByType(type);
    }
} 